/*-------------------------------------------------------------------------
 *
 * pg_crc32c_sse42_choose.c
 *	  选择 Intel SSE 4.2 和软件 CRC-32C 实现之间的选择。
 *
 * 在第一次调用时，检查运行所在的 CPU 是否支持 Intel SSE 4.2。如果支持，则使用特殊的 SSE 指令进行 CRC-32C 计算。否则，退回到纯软件实现（按 8 切片）。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/port/pg_crc32c_sse42_choose.c
 *
 *-------------------------------------------------------------------------
 */

#include "c.h"

#ifdef HAVE__GET_CPUID
#include <cpuid.h>
#endif

#ifdef HAVE__CPUID
#include <intrin.h>
#endif

#include "port/pg_crc32c.h"

static bool fc_pg_crc32c_sse42_available(void)
{
	unsigned int fc_exx[4] = {0, 0, 0, 0};

#if defined(HAVE__GET_CPUID)
	__get_cpuid(1, &fc_exx[0], &fc_exx[1], &fc_exx[2], &fc_exx[3]);
#elif defined(HAVE__CPUID)
	__cpuid(fc_exx, 1);
#else
#error cpuid instruction not available
#endif

	return (fc_exx[2] & (1 << 20)) != 0;	/* SSE 4.2 */
}

/*
 * 这是在第一次调用时调用的。它替换了函数指针
 * 以便后续调用直接路由到选定的实现。
 */
static pg_crc32c
fc_pg_comp_crc32c_choose(pg_crc32c fc_crc, const void *fc_data, size_t fc_len)
{
	if (fc_pg_crc32c_sse42_available())
		pg_comp_crc32c = pg_comp_crc32c_sse42;
	else
		pg_comp_crc32c = pg_comp_crc32c_sb8;

	return pg_comp_crc32c(fc_crc, fc_data, fc_len);
}

pg_crc32c	(*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len) = fc_pg_comp_crc32c_choose;
